
# Evil
# Remove me when the PIL fixes their PNG support w.r.t transparency.
import PILPatch

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, CondPageBreak, Image
import reportlab.lib.styles as styles
from reportlab.lib.enums import *

from reportlab.lib.units import cm
import reportlab.lib.pagesizes as pagesizes

import reportlab.rl_config
import sys

reportlab.rl_config.TTFSearchPath = sys.path



from wordaxe.rl import NewParagraph
from wordaxe import hyphRegistry
from wordaxe.DictHyphenator import DictHyphenator
hyphRegistry['RU'] = DictHyphenator('ru', 4)
hyphRegistry['EN'] = DictHyphenator('en', 4)


class DefaultConfig:
    pagesize = pagesizes.landscape(pagesizes.A5)
    font = ('DroidSerif.ttf', 'DroidSerif-Bold.ttf', 'DroidSerif-Italic.ttf', 'DroidSansMono.ttf')
    fontsize = 10
    linespacing = 1.2
    margins = 1 * cm
    pageinfo = "%(last)s %(fi)s. %(mi)s.: %(title)s / %(page)d"
    firstpageinfo = ""
    imagemargins = 1 * cm
    enableimages = True

    h1fontscale = 1.6
    h1spacebefore = 1.25
    h1spaceafter = 1.25

    h2fontscale = 1.4
    h2spacebefore = 0.75
    h2spaceafter = 0.75

    h3fontscale = 1.2
    h3spacebefore = 0.5
    h3spaceafter = 0.5

    h4fontscale = 1
    h4spacebefore = 0.5
    h4spaceafter = 0.5

    hfont = 'Bold'
    halignment = TA_CENTER

    textfont = 'Regular'
    paraindent = 1.0
    textalignment = TA_JUSTIFY

    emfont = 'Italic'
    emleftindent = 0.2
    emrightindent = 0.2

    verseleftindent = 0.1
    verserightindent = 0
    versespacer = 0.5

    authoralignment = TA_RIGHT

    footerfontscale = 0.8
    footerx = 1.25
    footery = 0.5
    
def setupfonts(fontlist):

    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont

    for k,v in fontlist.iteritems():
        pdfmetrics.registerFont(TTFont(k, v))

def setupstyles(stylesheet, style, Config, lang):

    text = styles.ParagraphStyle('Text', style)
    text.fontName = Config.textfont
    text.fontSize = Config.fontsize
    text.leading = int(Config.fontsize * Config.linespacing)
    text.allowWidows = 0

    if lang == 'ru':
        text.language = 'RU'
        text.hyphenation = True
    elif lang == 'en':
        text.language = 'EN'
        text.hyphenation = True       

    leading = text.leading

    h1 = styles.ParagraphStyle('H1', text)
    h1.fontName = Config.hfont
    h1.fontSize = int(Config.fontsize * Config.h1fontscale)
    h1.leading = leading * Config.h1fontscale
    h1.alignment = Config.halignment
    h1.spaceBefore = Config.h1spacebefore * Config.em
    h1.spaceAfter = Config.h1spaceafter * Config.em

    if hasattr(Config, 'hcolor'):
        h1.textColor = Config.hcolor

    h2 = styles.ParagraphStyle('H2', h1)
    h2.fontSize = int(Config.fontsize * Config.h2fontscale)
    h2.leading = leading * Config.h2fontscale
    h2.spaceBefore = Config.h2spacebefore * Config.em
    h2.spaceAfter = Config.h2spaceafter * Config.em

    h3 = styles.ParagraphStyle('H3', h2)
    h3.fontSize = int(Config.fontsize * Config.h3fontscale)
    h3.leading = leading * Config.h3fontscale
    h3.spaceBefore = Config.h3spacebefore * Config.em
    h3.spaceAfter = Config.h3spaceafter * Config.em

    h4 = styles.ParagraphStyle('H4', h3)
    h4.fontSize = int(Config.fontsize * Config.h4fontscale)
    h4.leading = leading * Config.h4fontscale
    h4.spaceBefore = Config.h4spacebefore * Config.em
    h4.spaceAfter = Config.h4spaceafter * Config.em

    em = styles.ParagraphStyle('Em', text)
    em.fontName = Config.emfont
    em.leftIndent = Config.pagesize[0] * Config.emleftindent
    em.rightIndent = Config.pagesize[0] * Config.emrightindent

    verse = styles.ParagraphStyle('Verse', text)
    verse.leftIndent = Config.pagesize[0] * Config.verseleftindent
    verse.rightIndent = Config.pagesize[0] * Config.verserightindent

    author = styles.ParagraphStyle('Author', text)
    author.alignment = Config.authoralignment

    # Change this only for 'Text' style.
    text.firstLineIndent = Config.paraindent * Config.em
    text.alignment = Config.textalignment

    stylesheet.add(text)
    stylesheet.add(h1)
    stylesheet.add(h2)
    stylesheet.add(h3)
    stylesheet.add(h4)
    stylesheet.add(em)
    stylesheet.add(author)
    stylesheet.add(verse)


def myFirstPage(canvas, doc, metadata, Config):
    canvas.setTitle(metadata['title'])
    canvas.setAuthor(' '.join(x for x in [metadata['last'], metadata['first'], metadata['middle']] if x != ''))

    if len(Config.firstpageinfo) > 0:
        canvas.saveState()
        canvas.setFont('Regular', int(Config.fontsize * Config.footerfontscale))
        metadata['page'] = doc.page
        canvas.drawString(Config.margins * Config.footerx,
                          Config.margins * Config.footery,
                          Config.firstpageinfo % metadata)
        canvas.restoreState()
    
def myLaterPages(canvas, doc, metadata, Config):
    if len(Config.pageinfo) > 0:
        canvas.saveState()
        canvas.setFont('Regular', int(Config.fontsize * Config.footerfontscale))
        metadata['page'] = doc.page
        canvas.drawString(Config.margins * Config.footerx, 
                          Config.margins * Config.footery, 
                          Config.pageinfo % metadata)
        canvas.restoreState()
    

def genbody(zbody, binaries, stylesheet, Config):

    for i in xrange(len(zbody)):
        if zbody[i] == '':
            zbody[i] = CondPageBreak(Config.pagesize[1] * 0.95 - (Config.margins * 2))
        elif zbody[i] == '*':
            zbody[i] = Spacer(1, Config.versespacer * Config.em)
        
        #hack
        elif zbody[i][0] == 'Text':
            zbody[i] = NewParagraph.Paragraph(zbody[i][1], stylesheet[zbody[i][0]])

        elif zbody[i][0] == 'Image':
            try:
                fbuf = binaries[zbody[i][1]]
                zbody[i] = Image(fbuf)
                zbody[i]._restrictSize(Config.pagesize[0] - (2 * max(Config.imagemargins, Config.margins)),
                                       Config.pagesize[1] - (2 * max(Config.imagemargins, Config.margins)))
                fbuf.seek(0)
            except:
                zbody[i] = Spacer(1, Config.versespacer * Config.em)

        else:
            zbody[i] = Paragraph(zbody[i][1], stylesheet[zbody[i][0]])

    return zbody


def go(filename, metadata, zbody, binaries, Config):

    Config.em = Config.fontsize * Config.linespacing

    fonts = { 'Regular' : Config.font[0],
              'Bold' : Config.font[1],
              'Italic' : Config.font[2],
              'Mono' : Config.font[3] }
    setupfonts(fonts)

    samplestyles = styles.getSampleStyleSheet()
    normalstyle = samplestyles["Normal"]

    stylesheet = styles.StyleSheet1()
    setupstyles(stylesheet, normalstyle, Config, metadata['lang'])

    doc = SimpleDocTemplate(filename)
    doc.pagesize = Config.pagesize
    doc.topMargin = Config.margins
    doc.bottomMargin = Config.margins
    doc.leftMargin = Config.margins
    doc.rightMargin = Config.margins

    print 'Prepare...'
    body = genbody(zbody, binaries, stylesheet, Config)
    print 'OK'

    print 'Build...'
    doc.build(body, 
              onFirstPage = (lambda a, b : myFirstPage(a, b, metadata, Config)), 
              onLaterPages = (lambda a, b : myLaterPages(a, b, metadata, Config)))
    print 'OK'

    
#if __name__ == "__main__":
#    go('test.pdf', {}, ['Text', 'Hello world'])
